
use std::time::Duration;
// 数据库连接
use crate::database;
use crate::database::divination::Divination;

// 自定义返回
// use crate::handler::jwt::Claims;
use crate::CustomResult::*;
use axum::response::Json;
use reqwest;
use serde::{Deserialize, Serialize};

/************************** 删除 ***************************/
// api
// '/api/divination/delete

//请求参数
#[derive(Serialize, Deserialize, Debug, Default)]
pub struct RequestDelete {
    pub id: i32,
}

//返回参数
#[derive(Serialize, Deserialize, Debug, Default)]
#[serde(default)]
pub struct ResponseDelete {
    pub code: i32,
    pub data: Option<i32>,
    pub msg: Option<String>,
}

//handler
pub async fn delete(Json(param): Json<RequestDelete>) -> CustomResult<Json<ResponseDelete>> {
    let _ = database::user::delete(param.id).await?;
    Ok(Json(ResponseDelete {
        code: 200,
        data: None,
        msg: Some("删除成功".to_string()),
    }))
}

/************************** 列表  ***************************/
// api
//'/api/divination/list'

//请求参数
//()

//返回参数
//ResponseList

//handler
pub async fn list() -> CustomResult<Json<ResponseList>> {
    let rows = database::user::list().await?;
    Ok(Json(ResponseList {
        code: 200,
        data: rows,
        msg: None,
    }))
}

/************************** 分页  ***************************/
//api
//'/api/divination/pages'

//请求参数
#[derive(Serialize, Deserialize, Debug, Default)]
pub struct RequestList {
    pub page: u32,
    pub page_size: u32,
}

//返回参数
#[derive(Serialize, Deserialize, Debug, Default)]
#[serde(default)]
pub struct ResponseList {
    pub code: i32,
    pub data: Vec<database::user::User>,
    pub msg: Option<String>,
}

//handler
pub async fn pages(Json(param): Json<RequestList>) -> CustomResult<Json<ResponseList>> {
    let page = param.page;
    let page_size = param.page_size;
    let rows = database::user::pages(page, page_size).await?;

    Ok(Json(ResponseList {
        code: 200,
        data: rows,
        msg: None,
    }))
}

/************************** gpt产生一次摇卦结果  ***************************/
//api
//'/api/divination/create_by_gpt'

//请求参数
#[derive(Serialize, Deserialize, Debug, Default)]
pub struct RequestCreateByGpt {
    pub user_id: i32, //用户id
}

//返回参数
#[derive(Serialize, Deserialize, Debug, Default)]
#[serde(default)]
pub struct ResponseCreateByGpt {
    pub code: i32,
    pub data: Option<Divination>,
    pub msg: Option<String>,
}

 /* claims: Claims, */
pub async fn create_by_gpt(
    Json(param): Json<RequestCreateByGpt>,
) -> CustomResult<Json<ResponseCreateByGpt>> {

    // let user_id = claims.user_id;
    let user_id = param.user_id;
    
    //1 查询t_user 指定用户数据 暂不考虑登录
    let _ = database::user::find_by_id(user_id).await?;

    //2 查询t_divination 满足指定用户  满足指定日期的数据
    let _ = database::divination::get_user_today_divination_count(user_id).await?;

    //3 创建一次gpt抽签请求
    let client = reqwest::Client::new();
    let url = "https://api.openai.com/v1/chat/completions";
    let body = r#"
{
    "model": "gpt-3.5-turbo",
    "messages": [
      {
        "role": "system",
        "content": "你是一名长期从事易学工作的大师，尤其擅长观音灵签，请每次帮我抽一次签，不需要询问是否抽签，直接返回抽签的结果，结果要包含抽中灵签的详细信息包括:第几号签(number字段,例如:第18号签), 签名(name字段,例如:苏秦不第), 签等级(level字段,例如:上上签) 签诗(poem字段,例如: 鲸鱼未变守江河，不可升腾更望高;异日峥嵘身变化，许君一跃跳龙门。), 解签(poem_interpretation字段,例如: 得忍且忍。得耐且耐。须待时至。功名还在。), 对事业的影响(career_prediction字段), 对爱情的影响(love_prediction字段) 。并以 json 形式返回。 该json 只包含上诉描述的字段不包含其它信息"
      },
      {
        "role": "user",
        "content": "Hello!"
      }
    ]
}"#;
    let client_response = client
        .post(url)
        .header("Content-Type", "application/json")
        .header("Accept", "application/json")
        .header(
            "Authorization",
            "Bearer sk-proj-s9pNA6x5Mn1FmMf0JvPsT3BlbkFJxUmAZMTPFroOmqW6q695",
        )
        .header("OpenAI-Project", "proj_a0Lm1DMhsXU1wgyTNZAxBDSD")
        .body(body)

        .timeout(Duration::from_secs(15))
        .send()
        .await
        .map_err(|e| CustomError::TipError(e.to_string()))?;
    
    // 4 检查gpt抽签响应
    if client_response.status().is_success() {
        println!("请求成功");
        let parsed_data = client_response
            .json::<serde_json::Value>()
            .await
            .map_err(|e| CustomError::TipError(e.to_string()))?;

        let choices = parsed_data["choices"]
            .as_array()
            .ok_or(CustomError::TipError("没有choices字段".into()))?;
        let content_str = choices[0]["message"]["content"]
            .as_str()
            .ok_or(CustomError::TipError("没有content字段".into()))?;

        //content对应的字符串 -> json
        let content_json: serde_json::Value =
            serde_json::from_str(content_str).map_err(|e| e.to_string())?;

        let number = content_json
            .get("number")
            .and_then(|v| v.as_str())
            .unwrap_or("");
        let name = content_json
            .get("name")
            .and_then(|v| v.as_str())
            .unwrap_or("");
        let level = content_json
            .get("level")
            .and_then(|v| v.as_str())
            .unwrap_or("");
        let poem = content_json
            .get("poem")
            .and_then(|v| v.as_str())
            .unwrap_or("");
        let poem_interpretation = content_json
            .get("poem_interpretation")
            .and_then(|v| v.as_str())
            .unwrap_or("");
        let career_prediction = content_json
            .get("career_prediction")
            .and_then(|v| v.as_str())
            .unwrap_or("");
        let love_prediction = content_json
            .get("love_prediction")
            .and_then(|v| v.as_str())
            .unwrap_or("");
        let remark = "ai";

        // 5 抽签信息插入db
        let divination_id = database::divination::insert(
            number,
            name,
            level,
            poem,
            poem_interpretation,
            career_prediction,
            love_prediction,
            user_id,
            remark,
        )
        .await?;
        // 6 返回抽签信息
        let divination = database::divination::find_by_id(divination_id as i32).await?;

        Ok(Json(ResponseCreateByGpt {
            code: 200,
            data: Some(divination),

            msg: None,
        }))
    } else {
        Err("抽签失败".into())
    }
}
